package com.lawyer.uitls;

import java.io.UnsupportedEncodingException;
import java.security.AlgorithmParameters;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Security;
import java.security.Signature;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.digest.DigestUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;

import com.alibaba.fastjson.JSON;
import com.lawyer.model.WxUserInfo;
import com.lawyer.model.wx.WxPhone;
import com.qiniu.util.Hex;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;

public class WXUtils {

	protected final Logger logger = LoggerFactory.getLogger(this.getClass());

	public static WxUserInfo getUserInfo(String encryptedData, String sessionKey, String iv) {
		// 被加密的数据
		byte[] dataByte = Base64.getDecoder().decode(encryptedData);
		// 加密秘钥
		byte[] keyByte = Base64.getDecoder().decode(sessionKey);
		// 偏移量
		byte[] ivByte = Base64.getDecoder().decode(iv);
		try {
			// 如果密钥不足16位，那么就补足. 这个if 中的内容很重要
			int base = 16;
			if (keyByte.length % base != 0) {
				int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
				byte[] temp = new byte[groups * base];
				Arrays.fill(temp, (byte) 0);
				System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
				keyByte = temp;
			}
			// 初始化
			Security.addProvider(new BouncyCastleProvider());
			Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
			SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
			AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
			parameters.init(new IvParameterSpec(ivByte));
			cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
			byte[] resultByte = cipher.doFinal(dataByte);
			if (null != resultByte && resultByte.length > 0) {
				String result = new String(resultByte, "UTF-8");
				System.out.println("WxUserInfo解密后的Josn=====" + result);
				WxUserInfo userInfo = JSON.parseObject(result, WxUserInfo.class);
				return userInfo;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;

	}

	/**
	 * @param encryptedData
	 * @param sessionKey
	 * @param iv
	 * @return 解密
	 */
	public static WxPhone unEncryptedData(String encryptedData, String sessionKey, String iv) {
		// 被加密的数据
//		byte[] dataByte = Base64.decode(encryptedData);
		byte[] dataByte = Base64.getDecoder().decode(encryptedData);
		// 加密秘钥
		byte[] keyByte = Base64.getDecoder().decode(sessionKey);
		// 偏移量
		byte[] ivByte = Base64.getDecoder().decode(iv);
		try {
			// 如果密钥不足16位，那么就补足. 这个if 中的内容很重要
			int base = 16;
			if (keyByte.length % base != 0) {
				int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
				byte[] temp = new byte[groups * base];
				Arrays.fill(temp, (byte) 0);
				System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
				keyByte = temp;
			}
			// 初始化
			Security.addProvider(new BouncyCastleProvider());
			Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
			SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
			AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
			parameters.init(new IvParameterSpec(ivByte));
			cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
			byte[] resultByte = cipher.doFinal(dataByte);
			if (null != resultByte && resultByte.length > 0) {
				String result = new String(resultByte, "UTF-8");
				System.out.println("WxPhone解密后的Josn=====" + result);
				return JSON.parseObject(result, WxPhone.class);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;

	}

	/**
	 * 个推推送消息加密码
	 */
	public static String getSHA256Str(String str) throws Exception {
		MessageDigest messageDigest;
		String encdeStr = "";
		try {
			messageDigest = MessageDigest.getInstance("SHA-256");
			byte[] hash = messageDigest.digest(str.getBytes("UTF-8"));
			encdeStr = Hex.encodeHexString(hash);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return encdeStr;
	}

	/**
	 * 支付生成签名
	 * 
	 * @param privateKey
	 *            私钥
	 * @param text
	 *            明文
	 * @return
	 */
	public static String sign(String text) {
		byte[] signed = null;
		try {
			Resource resource = new DefaultResourceLoader().getResource("classpath:template/apiclient_key.pem");
			PrivateKey privateKey = PemUtil.loadPrivateKey(resource.getInputStream());
			MessageDigest messageDigest;
			messageDigest = MessageDigest.getInstance("SHA-256");
			messageDigest.update(text.getBytes());
			byte[] outputDigest_sign = messageDigest.digest();
			Signature Sign = Signature.getInstance("SHA256withRSA");
			Sign.initSign(privateKey);
			Sign.update(outputDigest_sign);
			signed = Sign.sign();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return java.util.Base64.getEncoder().encodeToString(signed);
	}

	/**
	 * 生成签名
	 * 
	 * @param map
	 * @return
	 */
	public static String getPaySign(Map<String, String> map, String apiV3Key) {

		String result = "";
		try {
			List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(map.entrySet());
			// 对所有传入参数按照字段名的 ASCII 码从小到大排序（字典序）
			Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {

				public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
					return (o1.getKey()).toString().compareTo(o2.getKey());
				}
			});

			// 构造签名键值对的格式
			StringBuilder sb = new StringBuilder();
			for (Map.Entry<String, String> item : infoIds) {
				if (item.getKey() != null || item.getKey() != "") {
					String key = item.getKey();
					String val = item.getValue();
					if (!(val == "" || val == null)) {
						sb.append(key + "=" + val + "&");
					}
				}

			}

			result = sb.toString();
			result = result.substring(0, result.length() - 1);
			result = result + "&key=" + apiV3Key;
			System.out.println("拼接字符串：" + result);
			// 进行MD5加密
			result = DigestUtils.md5Hex(result).toUpperCase();
			System.out.println("加密后的字符串：" + result);
		} catch (Exception e) {
			return null;
		}
		return result;
	}
}